/*
 *  Copyright 2008 The MITRE Corporation (http://www.mitre.org/). All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.mitre.mrald.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.sql.Connection;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.mitre.mrald.control.AbstractStep;
import org.mitre.mrald.control.MsgObject;
import org.mitre.mrald.control.WorkflowStepException;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 *  Facility for translating XML files using XSLT.
 *
 *@author     jchoyt
 *@created    August 30, 2001
 */
public class XSLTranslator extends AbstractStep
{
    Connection conn;
    MsgObject msg;
    //Statement s;


    /*
     *  text like <:exmaple:> are to be replaced before the query is used - kinda like a prepared statement
     */
    /**
     *  Constructor for the FormUtils object
     *
     *@since
     */
    public XSLTranslator() { }


    /**
     *  Takes an XML and an XSL file and returns a StringBuffer containing the
     *  XSLT translation of the xml file.
     *
     *@param  xmlFile  XML File to use
     *@param  xslFile  XSL File to use
     *@return          A StringBuffer of the translated file
     */
    public static StringBuffer xslTransform( File xmlFile, File xslFile )
    {
        Document document;
        DocumentBuilderFactory factory =
                DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware( false );
        factory.setValidating( false );
        try
        {
        	// MraldOutFile.logToFile( Config.getProperty("LOGFILE") , "XSLTranslator: XMLFile Name " + xmlFile.getName() );

            Reader reader = new BufferedReader( new FileReader( xmlFile ) );
            InputSource datafile = new InputSource( reader );
            DocumentBuilder builder = factory.newDocumentBuilder();
            document = builder.parse( datafile );
            /*
             *  set up tranformer with xsl file
             */
            TransformerFactory tFactory =
                    TransformerFactory.newInstance();
            StreamSource stylesource = new StreamSource( xslFile );
            Transformer transformer = tFactory.newTransformer( stylesource );
            /*
             *  set up source with xml file
             */
            DOMSource source = new DOMSource( document );
            StringWriter ret = new StringWriter();
            StreamResult result = new StreamResult( ret );
            transformer.transform( source, result );

            return ret.getBuffer();
        }
        catch ( TransformerConfigurationException tce )
        {
            tce.printStackTrace();
            // Error generated by the parser
            throw new RuntimeException( "\n** Transformer Factory error  ",  tce );
        }
        catch ( TransformerException te )
        {
            // Error generated by the parser
            throw new RuntimeException( "\n** Transformation error ",  te );
        }
        catch ( SAXException sxe )
        {
            // Error generated by this application
            // (or a parser-initialization error)
            throw new RuntimeException( "\n** SAXException error ",  sxe );
        }
        catch ( ParserConfigurationException pce )
        {
            // Parser with specified options can't be built
            throw new RuntimeException( "\n** ParseConfiguration error ", pce );
        }
        catch ( FileNotFoundException ioe )
        {
            // I/O error
            throw new RuntimeException( "\n** FileNotFoundException error ", ioe );
        }
        catch ( IOException ioe )
        {
            // I/O error
            throw new RuntimeException( "\n** IOException error ",  ioe );
        }
    }


    /**
     *  Takes an xml in a string and the path to an xsl file and does the XSL tranlsation
     *
     *@param  formXml                    A string containing an xml file (not the name of an xml file)
     *@param  xsl                        A string containing the path to an xsl file
     *@return                            Description of the Returned Value
     *@exception  WorkflowStepException  Description of Exception
     *@since
     */
    public static StringBuffer xslTransform( String formXml, String xsl )
        throws WorkflowStepException
    {
        Document document;
        DocumentBuilderFactory factory =
                DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware( false );
        factory.setValidating( false );


        try
        {
            File stylesheet = new File( xsl );
//            MraldOutFile.appendToFile( Config.getProperty( "LOGFILE" ), xsl );
            StringReader reader = new StringReader( formXml );
            InputSource datafile = new InputSource( reader );
            DocumentBuilder builder = factory.newDocumentBuilder();
            document = builder.parse( datafile );

            // Use a Transformer for output
            TransformerFactory tFactory =
                    TransformerFactory.newInstance();
            StreamSource stylesource = new StreamSource( stylesheet );
            Transformer transformer = tFactory.newTransformer( stylesource );

            DOMSource source = new DOMSource( document );
            StringWriter ret = new StringWriter();
            StreamResult result = new StreamResult( ret );
            transformer.transform( source, result );

            return ret.getBuffer();
        }
        catch ( TransformerConfigurationException tce )
        {
            tce.printStackTrace();
            // Error generated by the parser
            throw new WorkflowStepException( "\n** Transformer Factory error  " + tce.getMessage() );
        }
        catch ( TransformerException te )
        {
            // Error generated by the parser
            throw new WorkflowStepException( "\n** Transformation error " + te.getMessage() );
        }
        catch ( SAXException sxe )
        {
            // Error generated by this application
            // (or a parser-initialization error)
            throw new WorkflowStepException( "\n** SAXException error " + sxe.getMessage() );
        }
        catch ( ParserConfigurationException pce )
        {
            // Parser with specified options can't be built
            throw new WorkflowStepException( "\n** ParseConfiguration error " + pce.getMessage() );
        }
        catch ( IOException ioe )
        {
            // I/O error
            throw new WorkflowStepException( "\n** IOException error " + ioe.getMessage() );
        }
    }


    /**
     *  Gets the Html attribute of the FormUtils object
     *
     *@param  msgObject                  Description of Parameter
     *@exception  WorkflowStepException  Description of Exception
     *@since
     */
    public void execute( MsgObject msgObject )
        throws WorkflowStepException
    {
        try
        {

            msg = msgObject;

            //String formTitle = msg.getValue( "PageTitle" )[0];
            //Get the form XML from File
            String formXml = msg.getValue( "xmlFile" )[0];

            // MraldOutFile.logToFile( Config.getProperty("LOGFILE") , "XSLTranslator: Execute : XMLFile Name " + formXml );

            String xmlString = null;
            //MraldOutFile.appendToFile(  Config.getProperty( "LOGFILE" ) ,"XSLTranslator: execute " + formXml );

            BufferedReader in = new BufferedReader( new FileReader( formXml ) );

            if ( in == null )
            {
                //MraldOutFile.appendToFile(  Config.getProperty( "LOGFILE" ) ,"XSLTranslator: File not found ");
                throw new WorkflowStepException( "IOException in XSLTranslator.execute() " + formXml + " not found." );
            }
            String line = null;
            if ( in.readLine() == null )
            {
                //MraldOutFile.appendToFile(  Config.getProperty( "LOGFILE" ) ,"XSLTranslator: File does not have data");
                throw new WorkflowStepException( "IOException in XSLTranslator.execute(). Could not read file " + formXml );
            }
            xmlString = in.readLine();
            while ( ( line = in.readLine() ) != null )
            {
                xmlString += line;
                //MraldOutFile.appendToFile(  Config.getProperty( "LOGFILE" ) ,"XSLTranslator: output : " + line );

            }
            /*
             *  convert to html and show to the user
             */
            //Check if the XSL Stylesheet is specified in the HTML form - if it
            //isn't then use the default
            String formXsl = msg.getValue( "formStylesheet" )[0];
            if ( formXsl == null )
            {
                formXsl = Config.getProperty( "formStylesheet" );
                //MraldOutFile.appendToFile(  Config.getProperty( "LOGFILE" ) ,"XSLTranslator: stylesheet : Had to get from default." );
            }

            StringBuffer formHtml = XSLTranslator.xslTransform( xmlString, formXsl );
            //MraldOutFile.appendToFile(  Config.getProperty( "LOGFILE" ) ,"XSLTranslator: stylesheet :" + formHtml );

            msg.SetOutPrintWriter();

            String contentType = msg.getValue( "mraldContentType" )[0];
            msg.setContentType( contentType );
            msg.setHeader( "Content-Disposition", "inline;" );

            PrintWriter out = msg.getOutPrintWriter();
            out.println( formHtml );
        }
        catch ( IOException mge )
        {
            throw new WorkflowStepException( "IOException in XSLTranslator.execute() " + mge.getMessage() );
        }
        catch ( org.mitre.mrald.control.MsgObjectException e )
        {
            throw new WorkflowStepException( "MsgObjectException in FormUtils.execute() " + e.getMessage() );
        }

    }
}

